#ifndef UTILS_H
#define UTILS_H

/* macros with strict type-checking, based in the Linux linux/kernel.h */

/**
 * Checks at compile time if x and y are of the same type.
 *
 * @return always return 1.
 */
#define sametype( x, y )                                                      \
  ({                                                                          \
  __typeof__(x) _x = (x);                                                     \
  __typeof__(y) _y = (y);                                                     \
  (void) (&_x == &_y);                                                        \
  1; })

#define typecheck( type, x )                                                  \
  ({                                                                          \
  type __dummy1;                                                              \
  typeof(x) __dummy2;                                                         \
  (void)( &__dummy1 == &__dummy2 );                                           \
  1; })

#define min( x, y )                                                           \
  ({                                                                          \
  sametype( (x), (y) );                                                       \
  (typeof(x))( (x) < (y) ? (x) : (y) );                                       \
  })

#define max( x, y )                                                           \
  ({                                                                          \
  sametype( (x), (y) );                                                       \
  (typeof(x))( (x) > (y) ? (x) : (y) );                                       \
  })

#define swap( x, y )                                                          \
  ({                                                                          \
  sametype( (x), (y) );                                                       \
  __typeof__(x) tmp = (x);                                                    \
  (x) = (y);                                                                  \
  (y) = tmp;                                                                  \
  })

#define pow2( n )  ( (n)*(n) )

static inline int
double_is_equal( const double a, const double b, const double threshold )
{
  double c = a - b;
  if ( c < 0.0 )
    c = -c;
  return c < threshold;
}

#endif /* UTILS_H */
